using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Collections;

namespace Web.Ajax.Controls
{
    [ToolboxData("<{0}:Calendar runat=\"server\" />")]    
    public class Calendar : WebControl
    {
        public Calendar()
        {
            StartYear = (DateTime.Now.Year-(YearsInMenu/2));
            if (Configuration.Settings.Current.ValidatorType != null)
                ValidatorType = Configuration.Settings.Current.ValidatorType;
        }


		public static void RegisterResources(Web.Ajax.Page p)
		{
			if (p == null)
				return;
			p.RegisterJavascriptFile(Resources.Javascript.AjaxControl);
			p.RegisterJavascriptFile(Resources.Javascript.Calendar);
			p.RegisterJavascriptFile(Resources.Javascript.PopupMenu);
			p.RegisterJavascriptFile(Resources.Javascript.Validator);
			p.RegisterStyleSheet(Resources.StyleSheets.Calendar);
			p.RegisterStyleSheet(Resources.StyleSheets.PopupMenu);

		}

        protected override void OnInit(EventArgs e)
        {  
            base.OnInit(e);
            if (Page != null)
            {
                string val=Page.Request.Form[JavascriptId+"_value"];
                if (!string.IsNullOrEmpty(val))
                {
                    object o=Json.ConvertFromJson(typeof(DateTime), val);
                    if(o is DateTime)
                        Date = (DateTime)o;
                }
				RegisterResources(Page);
            }
        }

        private string textBoxWidth;
        /// <summary>
        /// The width of the Textbox that will display the selected date.
        /// </summary>
        public string TextBoxWidth
        {
            get { return textBoxWidth; }
            set { textBoxWidth = value; }
        }

        private string format="dd-MMM-yyyy";
        /// <summary>
        /// The format to use when displaying dates as strings. d dd ddd M MM MMM MMMM yyyy yy are supported.
        /// </summary>
        public string Format
        {
            get { return format; }
            set { format = value; }
        }

        private DateTime? date;
        /// <summary>
        /// The currently selected date.
        /// </summary>
        public DateTime? Date
        {
            get { return date; }
            set { date = value; }        
        }

        private DateTime? minDate;
        /// <summary>
        /// The minimum date that can be selected.
        /// </summary>
        public DateTime? MinDate
        {
            get { return minDate; }
            set { minDate = value; }
        }

        private DateTime? maxDate;
        /// <summary>
        /// The maximum date that can be selected.
        /// </summary>
        public DateTime? MaxDate
        {
            get { return maxDate; }
            set { maxDate = value; }
        }

        private int leftOffset = 0;
        /// <summary>
        /// The left offset to add to the position calculation when displaying the calendar popup.
        /// </summary>
        public int LeftOffset
        {
            get { return leftOffset; }
            set { leftOffset = value; }
        }

        private int topOffset = 0;
        /// <summary>
        /// The top offset to add to the position calculation when displaying the calendar popup.
        /// </summary>
        public int TopOffset
        {
            get { return topOffset; }
            set { topOffset = value; }
        }

        private int startYear = 0;
        /// <summary>
        /// The initial year to display in the year selection dropdown.
        /// </summary>
        public int StartYear
        {
            get { return startYear; }
            set { startYear = value; }
        }


        private int yearCols = 5;
        /// <summary>
        /// The number of columns in the year popupmenu.
        /// </summary>
        public int YearCols
        {
            get { return yearCols; }
            set { yearCols = value; }
        }

        private int yearsInMenu = 25;
        /// <summary>
        /// The number of years in the year popupmenu.
        /// </summary>
        public int YearsInMenu
        {
            get { return yearsInMenu; }
            set { yearsInMenu = value; }
        }


        private string onDateChanged;
        /// <summary>
        /// The javascript to call when the date has been changed. 
        /// The javascript will be invoked using eval(). 
        /// </summary>
        public string OnDateChanged
        {
            get { return onDateChanged; }
            set { onDateChanged = value; }
        }

        private string popupPosition="b";
        /// <summary>
        /// The position to show the calendar popup relative to the source (textbox and image).
        /// l = left, t = top, b = bottom, r = right, m = vertical middle, c = horizontal center.
        /// The default is 'bl'
        /// </summary>
        public string PopupPosition
        {
            get { return popupPosition; }
            set { popupPosition = value; }
        }

        private string minCal;
        /// <summary>
        /// The server id of another calendar control whose selected date 
        /// is to be used as min date. 
        /// </summary>
        public string MinCal
        {
            get
            {
                if (string.IsNullOrEmpty(minCal))
                    return null;
                Control c = Parent.FindControl(minCal);
                if (c != null&&c is Calendar)
				    return ((Calendar)c).JavascriptId;
                return null;
            }
            set { minCal = value; }
        }

        private string maxCal;
        /// <summary>
        /// The server id of another calendar control whose selected date 
        /// is to be used as the max date.
        /// </summary>
        public string MaxCal
        {
            get 
            {
                if (string.IsNullOrEmpty(maxCal))
                    return null;
                Control c = Parent.FindControl(maxCal);
                if (c != null&&c is Calendar)
				    return ((Calendar)c).JavascriptId;
                return null; 
            }
            set { maxCal = value; }
        }

        private bool follow=true;
        /// <summary>
        /// Display the month selected in the MinCal or MaxCal when the date is not set. The default is true.
        /// </summary>
        public bool Follow
        {
            get { return follow; }
            set { follow = value; }
        }

        private bool required;
        /// <summary>
        /// Indicates that this is a required field. A client side call to IsValid
        /// on the calendar control will return false if no date is selected.
        /// </summary>
        public bool Required
        {
            get { return required; }
            set { required = value; }
        }

        private string sessionId;
        /// <summary>
        /// The session id to use to store the selected date. 
        /// If this is set, the selected date will be stored in a browser cookie
        /// and set to the value of this cookie on page load.
        /// </summary>
        public string SessionId
        {
            get { return sessionId;  }
            set { sessionId = value; }
        }

        private string propertyName;
        public string PropertyName
        {
            get { return propertyName; }
            set { propertyName = value; }
        }

		public string Group
		{
			get;
			set;
		}

		public string pid
		{
			get
			{
				return Group + "." + PropertyName;
			}
			set
			{
				var parts=value.Split('.');
				Group = parts[0];
				PropertyName=value.Substring(parts[0].Length+1);
			}
		}

        private string validatorType;
        public string ValidatorType
        {
            get { return validatorType; }
            set { validatorType = value; }
        }

        private bool validateCalled = false;
        public void Validate()
        {
            if (validateCalled)
                return;
            validateCalled = true;
            isValid = true;
            if (Required && !Date.HasValue)
                isValid = false;
        }

        private bool isValid = false;
        public bool IsValid
        {
            get { Validate(); return isValid; }
        }

        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            writer.Write("<span id=\""+JavascriptId+"_src\" >");
            writer.Write("<input type=\"text\" class=\"DateTextBox\" readonly ");
            writer.Write("id=\""+JavascriptId+"_tb\" ");
            writer.Write("onclick=\"" + JavascriptId + ".Show();\" ");
            if (!string.IsNullOrEmpty(TextBoxWidth))
                writer.Write("style=\"width:"+TextBoxWidth+"\"");
            writer.Write(" />");
			writer.Write("<img src=\"" + Resources.ImageUrl(Resources.Images.Calendar) + "\" class=\"DateImage\" ");
            writer.Write("onclick=\"" + JavascriptId + ".Show();\" ");    
            writer.Write(" />");
            writer.Write("</span>");
            if (Required)
                writer.Write("<img id=\"" + JavascriptId + "_val\"  src=\"" + Resources.ImageUrl(Resources.Images.Failure) + "\" class=\"CalendarValidator\" style=\"visibility:hidden;\" title=\"This is a required field.\" />");

            writer.Write("<input id=\"" + JavascriptId + "_value\" name=\"" + JavascriptId + "_value\" type=\"hidden\" style=\"display:none;\" />");
            
            RenderJavascriptStartTag(writer);
            writer.WriteLine("var " + JavascriptId + "=new Calendar('" + JavascriptId + "',"+LeftOffset.ToString()+","+TopOffset.ToString()+",'"+PopupPosition+"',"+Json.ConvertToJson(SessionId)+");");

			var properties = new Hashtable();
			properties["StartYear"] = StartYear;
			properties["YearCols"] = YearCols;
			properties["YearsInDropDown"] = yearsInMenu;

			if (Date.HasValue)
				writer.WriteLine(JavascriptId + ".SetDate(" + (Date.Value.Day - 1).ToString() + "," + (Date.Value.Month - 1).ToString() + "," + Date.Value.Year.ToString() + ");");                        
            			
			if (MinDate.HasValue)
				properties["MinDate"] = MinDate;
			if (MaxDate.HasValue)
				properties["MaxDate"] = MaxDate;
			if (!string.IsNullOrEmpty(Format))
				properties["Format"] = Format;
			if (!string.IsNullOrEmpty(OnDateChanged))
				properties["OnDateChanged"] = OnDateChanged;
			if (!string.IsNullOrEmpty(Group))
				properties["Group"] = Group;
			var MinCal = this.MinCal;
			var MaxCal = this.MaxCal;
			if (!string.IsNullOrEmpty(MinCal))
				properties["MinCal"] = MinCal;
			if (!string.IsNullOrEmpty(MaxCal))
				properties["MaxCal"] = MaxCal;

			properties["Follow"] = Follow;
			properties["Required"] = Required;
			if (!string.IsNullOrEmpty(ValidatorType))
				properties["ValidatorType"] = ValidatorType;
			if (!string.IsNullOrEmpty(PropertyName))
				properties["PropertyName"] = PropertyName;

			writer.WriteLine("$.extend(true, " + JavascriptId + ", " + Json.ConvertToJson(properties) + ");");


			/*
            RenderProperty(writer,"StartYear",StartYear);
			RenderProperty(writer, "YearCols", YearCols);
			RenderProperty(writer, "YearsInDropDown", yearsInMenu);	
			if (Date.HasValue)
				writer.WriteLine(JavascriptId + ".SetDate(" + (Date.Value.Day - 1).ToString() + "," + (Date.Value.Month - 1).ToString() + "," + Date.Value.Year.ToString() + ");");                        
			if (MinDate.HasValue)
                RenderProperty(writer, "MinDate", MinDate);
            if (MaxDate.HasValue)
                RenderProperty(writer, "MaxDate", MaxDate);
            if (!string.IsNullOrEmpty(Format))
                RenderProperty(writer, "Format", Format);
            if (!string.IsNullOrEmpty(OnDateChanged))
                RenderProperty(writer, "OnDateChanged", OnDateChanged);			
			if (!string.IsNullOrEmpty(Group))
				RenderProperty(writer, "Group", Group);
            string MinCal = this.MinCal;
            string MaxCal = this.MaxCal;
            if (!string.IsNullOrEmpty(MinCal))
                RenderProperty(writer,"MinCal",MinCal);
            if (!string.IsNullOrEmpty(MaxCal))
                RenderProperty(writer, "MaxCal", MaxCal);
            RenderProperty(writer, "Follow", Follow);
            RenderProperty(writer, "Required", Required);			 
            if (!string.IsNullOrEmpty(ValidatorType))
                RenderProperty(writer, "ValidatorType", ValidatorType);
            if (!string.IsNullOrEmpty(PropertyName))
                RenderProperty(writer, "PropertyName", PropertyName);
			*/


			if (validateCalled)
                writer.WriteLine(JavascriptId + ".IsValid();");
			if(!this.Enabled)
				writer.WriteLine(JavascriptId + ".Disable();");
            RenderJavascriptId(writer);
            RenderJavascriptEndTag(writer);
        }

		public string GetHtml()
		{
			var w = new System.IO.StringWriter();
			var hw = new System.Web.UI.HtmlTextWriter(w);
			Render(hw);
			return w.ToString();
		}
    }
}
